home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / potion.c < prev    next >
C/C++ Source or Header  |  1993-01-04  |  30KB  |  1,263 lines

  1. /*    SCCS Id: @(#)potion.c    3.1    92/12/10          */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #ifdef OVLB
  8. static void NDECL(ghost_from_bottle);
  9. static boolean FDECL(neutralizes, (struct obj *,struct obj *));
  10.  
  11. static int NEARDATA nothing, NEARDATA unkn;
  12. #endif /* OVLB */
  13.  
  14. extern boolean notonhead;    /* for long worms */
  15. #ifdef OVLB
  16. boolean notonhead = FALSE;
  17. #endif /* OVLB */
  18.  
  19. #ifdef OVLB
  20.  
  21. static const char NEARDATA beverages[] = { POTION_CLASS, 0 };
  22.  
  23. void
  24. make_confused(xtime,talk)
  25. long xtime;
  26. boolean talk;
  27. {
  28.     long old = HConfusion;
  29.  
  30.     if (!xtime && old) {
  31.         if (talk) {
  32.             if (Hallucination) You("feel less trippy now.");
  33.             else           You("feel less confused now.");
  34.         }
  35.         flags.botl = 1;
  36.     }
  37.     if (xtime && !old)
  38.         flags.botl = 1;
  39.     HConfusion = xtime;
  40. }
  41.  
  42. void
  43. make_stunned(xtime,talk)
  44. long xtime;
  45. boolean talk;
  46. {
  47.     long old = HStun;
  48.  
  49.     if (!xtime && old) {
  50.         if (talk) {
  51.             if (Hallucination) You("feel less wobbly now.");
  52.             else           You("feel a bit steadier now.");
  53.         }
  54.         flags.botl = 1;
  55.     }
  56.     if (xtime && !old) {
  57.         if (talk)
  58.             You("stagger....");
  59.         flags.botl = 1;
  60.     }
  61.     HStun = xtime;
  62. }
  63.  
  64. void
  65. make_sick(xtime, talk)
  66. long xtime;
  67. boolean talk;
  68. {
  69.     long old = Sick;
  70.  
  71. #ifdef POLYSELF
  72.     if (xtime && u.usym == S_FUNGUS) return;
  73. #endif
  74.     if (!xtime && old) {
  75.         if (talk) pline("What a relief!");
  76.         flags.botl = 1;
  77.     }
  78.     if (!old && xtime) {
  79.         You("feel deathly sick.");
  80.         flags.botl = 1;
  81.     }
  82.     Sick = xtime;
  83. }
  84.  
  85. void
  86. make_vomiting(xtime, talk)
  87. long xtime;
  88. boolean talk;
  89. {
  90.     long old = Vomiting;
  91.  
  92.     if(!xtime && old)
  93.         if(talk) You("feel much less nauseous now.");
  94.  
  95.     Vomiting = xtime;
  96. }
  97.  
  98.  
  99. void
  100. make_blinded(xtime, talk)
  101. long xtime;
  102. boolean talk;
  103. {
  104.     long old = Blinded;
  105.     boolean changed = 0;
  106.  
  107.     if (u.usleep) talk = FALSE;
  108.  
  109.     if (!xtime && old && !Blindfolded
  110. #ifdef POLYSELF
  111.         && haseyes(uasmon)
  112. #endif
  113.         ) {
  114.         if (talk) {
  115.         if (Hallucination)
  116.             pline("Far out!  Everything is all cosmic again!");
  117.         else           You("can see again.");
  118.         }
  119.         changed = TRUE;
  120.     }
  121.     if (xtime && !old && !Blindfolded
  122. #ifdef POLYSELF
  123.         && haseyes(uasmon)
  124. #endif
  125.         ) {
  126.         if (talk) {
  127.         if (Hallucination) pline("Oh, bummer!  Everything is dark!  Help!");
  128.         else           pline("A cloud of darkness falls upon you.");
  129.         }
  130.         changed = TRUE;
  131.  
  132.         /* Before the hero goes blind, set the ball&chain variables. */
  133.         if (Punished) set_bc(0);
  134.     }
  135.     Blinded = xtime;
  136.     if (changed) {
  137.         flags.botl = 1;
  138.         vision_full_recalc = 1;
  139.         if (Telepat) see_monsters();
  140.     }
  141. }
  142.  
  143. void
  144. make_hallucinated(xtime, talk, mask)
  145. long xtime;    /* nonzero if this is an attempt to turn on hallucination */
  146. boolean talk;
  147. long mask;    /* nonzero if resistance status should change by mask */
  148. {
  149.     boolean changed = 0;
  150. #ifdef LINT
  151.     const char *message = 0;
  152. #else
  153.     const char *message;
  154. #endif
  155.  
  156.     if (!xtime)
  157.         message = "Everything looks SO boring now.";
  158.     else
  159.         message = "Oh wow!  Everything seems so cosmic!";
  160.  
  161.     if (mask) {
  162.         if (HHallucination) changed = TRUE;
  163.  
  164.         if (!xtime) HHalluc_resistance |= mask;
  165.         else HHalluc_resistance &= ~mask;
  166.     } else {
  167.         if (!HHalluc_resistance && (!!HHallucination != !!xtime))
  168.         changed = TRUE;
  169.         HHallucination = xtime;
  170.     }
  171.  
  172.     if (changed) {
  173.         if (u.uswallow) {
  174.         swallowed(0);    /* redraw swallow display */
  175.         } else {
  176.         /* The see_* routines should be called *before* the pline. */
  177.         see_monsters();
  178.         see_objects();
  179.         }
  180.         flags.botl = 1;
  181.         if (!Blind && talk) pline(message);
  182.     }
  183. }
  184.  
  185. static void
  186. ghost_from_bottle()
  187. {
  188.     struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy);
  189.  
  190.     if (!mtmp) {
  191.         pline("This bottle turns out to be empty.");
  192.         return;
  193.     }
  194.     if (Blind) {
  195.         pline("As you open the bottle, something emerges.");
  196.         return;
  197.     }
  198.     pline("As you open the bottle, an enormous %s emerges!",
  199.         Hallucination ? rndmonnam() : (const char *)"ghost");
  200.     if(flags.verbose)
  201.         You("are frightened to death, and unable to move.");
  202.     nomul(-3);
  203.     nomovemsg = "You regain your composure.";
  204. }
  205.  
  206. int
  207. dodrink() {
  208.     register struct obj *otmp;
  209.     const char *potion_descr;
  210.  
  211.     if (Strangled) {
  212.         pline("If you can't breathe air, how can you drink liquid?");
  213.         return 0;
  214.     }
  215.     /* Is there a fountain to drink from here? */
  216.     if (IS_FOUNTAIN(levl[u.ux][u.uy].typ) && !Levitation) {
  217.         if(yn("Drink from the fountain?") == 'y') {
  218.             drinkfountain();
  219.             return 1;
  220.         }
  221.     }
  222. #ifdef SINKS
  223.     /* Or a kitchen sink? */
  224.     if (IS_SINK(levl[u.ux][u.uy].typ)) {
  225.         if (yn("Drink from the sink?") == 'y') {
  226.             drinksink();
  227.             return 1;
  228.         }
  229.     }
  230. #endif
  231.  
  232.     otmp = getobj(beverages, "drink");
  233.     if(!otmp) return(0);
  234. #ifndef NO_SIGNAL
  235.     otmp->in_use = TRUE;        /* you've opened the stopper */
  236. #endif
  237.     potion_descr = OBJ_DESCR(objects[otmp->otyp]);
  238.     if (potion_descr && !strcmp(potion_descr, "milky") && !rn2(13)) {
  239.         ghost_from_bottle();
  240.         useup(otmp);
  241.         return(1);
  242.     } else if (potion_descr && !strcmp(potion_descr, "smoky") && !rn2(13)) {
  243.         djinni_from_bottle(otmp);
  244.         useup(otmp);
  245.         return(1);
  246.     }
  247.     return dopotion(otmp);
  248. }
  249.  
  250. int
  251. dopotion(otmp)
  252. register struct obj *otmp;
  253. {
  254.     int retval;
  255.  
  256.     nothing = unkn = 0;
  257.     if((retval = peffects(otmp)) >= 0) return(retval);
  258.  
  259.     if(nothing) {
  260.         unkn++;
  261.         You("have a %s feeling for a moment, then it passes.",
  262.           Hallucination ? "normal" : "peculiar");
  263.     }
  264.     if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
  265.         if(!unkn) {
  266.             makeknown(otmp->otyp);
  267.             more_experienced(0,10);
  268.         } else if(!objects[otmp->otyp].oc_uname)
  269.             docall(otmp);
  270.     }
  271.     useup(otmp);
  272.     return(1);
  273. }
  274.  
  275. int
  276. peffects(otmp)
  277.     register struct obj    *otmp;
  278. {
  279.     register int i, ii, isdone;
  280.  
  281.     switch(otmp->otyp){
  282.     case POT_RESTORE_ABILITY:
  283.     case SPE_RESTORE_ABILITY:
  284.         unkn++;
  285.         if(otmp->cursed) {
  286.             pline("Ulch!  This makes you feel mediocre!");
  287.             break;
  288.         } else {
  289.             pline("Wow!  This makes you feel %s!",
  290.               (otmp->blessed) ? "great" : "good");
  291.             i = rn2(A_MAX);        /* start at a random point */
  292.             for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
  293.             if(ABASE(i) < AMAX(i)) {
  294.                 ABASE(i) = AMAX(i);
  295.                 /* only first found if not blessed */
  296.                 isdone = !(otmp->blessed);
  297.                 flags.botl = 1;
  298.             }
  299.             if(++i >= A_MAX) i = 0;
  300.             }
  301.             if((ABASE(A_STR) == AMAX(A_STR)) && (u.uhs >= 3))
  302.             losestr(1);        /* kludge - mrs */
  303.         }
  304.         break;
  305.     case POT_HALLUCINATION:
  306.         if (Hallucination || HHalluc_resistance) nothing++;
  307.         make_hallucinated(HHallucination +
  308.               rn1(200, 600 - 300*bcsign(otmp)), TRUE, 0L);
  309.         break;
  310.     case POT_WATER:
  311.         if(!otmp->blessed && !otmp->cursed) {
  312.             pline("This tastes like %swater.",
  313.                   otmp->spe == -1 ? "impure " : "");
  314.             lesshungry(rnd(otmp->spe == -1 ? 3 : 10));
  315.             break;
  316.         }
  317.         unkn++;
  318.         if(
  319. #ifdef POLYSELF
  320.            is_undead(uasmon) || is_demon(uasmon) ||
  321. #endif
  322.                 u.ualign.type == A_CHAOTIC) {
  323.             if(otmp->blessed) {
  324.             pline("This burns like acid!");
  325.             exercise(A_CON, FALSE);
  326. #ifdef POLYSELF
  327.             if (u.ulycn != -1) {
  328.                 Your("affinity to %s disappears!",
  329.                      makeplural(mons[u.ulycn].mname));
  330.                 if(uasmon == &mons[u.ulycn] && !Polymorph_control)
  331.                     rehumanize();
  332.                 u.ulycn = -1;
  333.             }
  334. #endif
  335.             losehp(d(2,6), "potion of holy water", KILLED_BY_AN);
  336.             } else if(otmp->cursed) {
  337.             You("feel quite proud of yourself.");
  338.             healup(d(2,6),0,0,0);
  339.             exercise(A_CON, TRUE);
  340.             }
  341.         } else
  342.             if(otmp->blessed) {
  343.             You("feel full of awe.");
  344.             make_sick(0L,TRUE);
  345.             exercise(A_WIS, TRUE);
  346.             exercise(A_CON, TRUE);
  347. #ifdef POLYSELF
  348.             if (u.ulycn != -1) {
  349.                 You("feel purified.");
  350.                 if(uasmon == &mons[u.ulycn] && !Polymorph_control)
  351.                     rehumanize();
  352.                 u.ulycn = -1;
  353.             }
  354. #endif
  355.             /* make_confused(0L,TRUE); */
  356.             } else {
  357.             if(u.ualign.type == A_LAWFUL) {
  358.                 pline("This burns like acid!");
  359.                 losehp(d(2,6), "potion of unholy water",
  360.                 KILLED_BY_AN);
  361.             } else
  362.                 You("feel full of dread.");
  363.             exercise(A_CON, FALSE);
  364.             }
  365.         break;
  366.     case POT_BOOZE:
  367.         unkn++;
  368.         pline("Ooph!  This tastes like %s!",
  369.               Hallucination ? "furniture polish" : "liquid fire");
  370.         if (!otmp->blessed) make_confused(HConfusion + d(3,8),FALSE);
  371.         /* the whiskey makes us feel better */
  372.         if(u.uhp < u.uhpmax) losehp(-1, "", 0); /* can't kill you */
  373.         lesshungry(10 * (2 + bcsign(otmp)));
  374.         exercise(A_WIS, FALSE);
  375.         if(otmp->cursed) {
  376.             You("pass out.");
  377.             multi = -rnd(15);
  378.             nomovemsg = "You awake with a headache.";
  379.         }
  380.         break;
  381.     case POT_ENLIGHTENMENT:
  382.         if(otmp->cursed) {
  383.             unkn++;
  384.             You("have an uneasy feeling...");
  385.         } else {
  386.             if (otmp->blessed) {
  387.                 (void) adjattrib(A_INT, 1, FALSE);
  388.                 (void) adjattrib(A_WIS, 1, FALSE);
  389.             }
  390.             You("feel self-knowledgeable...");
  391.             display_nhwindow(WIN_MESSAGE, FALSE);
  392.             enlightenment(FALSE);
  393.             pline("The feeling subsides.");
  394.         }
  395.         exercise(A_WIS, !otmp->cursed);
  396.         break;
  397.     case POT_INVISIBILITY:
  398.     case SPE_INVISIBILITY:
  399.         if(Invisible || See_invisible) nothing++;
  400.         else {
  401.              if(!Blind)
  402.                pline(Hallucination ?
  403.              "Far out, man!  You can see right through yourself!" :
  404.              "Gee!  All of a sudden, you can't see yourself.");
  405.              else
  406.                You("feel rather airy."), unkn++;
  407.         }
  408.         if (otmp->blessed && !(HInvis & FROMOUTSIDE)) {
  409.             nothing = 0;
  410.             if(yn("Do you want the invisibility to be permanent?")
  411.                 == 'n')
  412.                 HInvis += rn1(15,31);
  413.             else HInvis |= FROMOUTSIDE;
  414.         } else HInvis += rn1(15,31);
  415.         newsym(u.ux,u.uy);    /* update position */
  416.         if(otmp->cursed) {
  417.             pline("For some reason, you feel your presence is known.");
  418.             aggravate();
  419.         }
  420.         break;
  421.     case POT_SEE_INVISIBLE:
  422.         /* tastes like fruit juice in Rogue */
  423.     case POT_FRUIT_JUICE:
  424.         unkn++;
  425.         if(otmp->cursed)
  426.             pline("Yecch!  This tastes %s.",
  427.               Hallucination ? "overripe" : "rotten"
  428.              );
  429.         else pline (Hallucination ?
  430. #ifdef TUTTI_FRUTTI
  431.            "This tastes like 10%% real %s juice all-natural beverage." :
  432.            "This tastes like %s juice.", pl_fruit
  433. #else
  434.            "This tastes like 10%% real fruit juice all-natural beverage." :
  435.            "This tastes like fruit juice."
  436. #endif
  437.                 );
  438.         if (otmp->otyp == POT_FRUIT_JUICE) {
  439.             lesshungry(10 * (2 + bcsign(otmp)));
  440.             break;
  441.         }
  442.         if (!otmp->cursed) {
  443.             /* Tell them they can see again immediately, which
  444.              * will help them identify the potion...
  445.              */
  446.             make_blinded(0L,TRUE);
  447.         }
  448.         if (otmp->blessed)
  449.             HSee_invisible |= FROMOUTSIDE;
  450.         else
  451.             HSee_invisible += rn1(100,750);
  452.         set_mimic_blocking(); /* do special mimic handling */
  453.         see_monsters();    /* see invisible monsters */
  454.         newsym(u.ux,u.uy); /* see yourself! */
  455.         break;
  456.     case POT_PARALYSIS:
  457.         if(Levitation || Is_waterlevel(&u.uz))
  458.             You("are motionlessly suspended.");
  459.         else
  460.             Your("%s are frozen to the floor!",
  461.                 makeplural(body_part(FOOT)));
  462.         nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
  463.         exercise(A_DEX, FALSE);
  464.         break;
  465.     case POT_MONSTER_DETECTION:
  466.     case SPE_DETECT_MONSTERS:
  467.         if (monster_detect(otmp, 0))
  468.             return(1);        /* nothing detected */
  469.         exercise(A_WIS, TRUE);
  470.         break;
  471.     case POT_OBJECT_DETECTION:
  472.     case SPE_DETECT_TREASURE:
  473.         if (object_detect(otmp, 0))
  474.             return(1);        /* nothing detected */
  475.         exercise(A_WIS, TRUE);
  476.         break;
  477.     case POT_SICKNESS:
  478.         pline("Yecch!  This stuff tastes like poison.");
  479.         if (otmp->blessed) {
  480. #ifdef TUTTI_FRUTTI
  481.         pline("(But in fact it was mildly stale %s juice.)", pl_fruit);
  482. #else
  483.         pline("(But in fact it was mildly stale orange juice.)");
  484. #endif
  485.             if (pl_character[0] != 'H')
  486.                 losehp(1, "mildly contaminated potion",
  487.                     KILLED_BY_AN);
  488.         } else {
  489.             if(Poison_resistance)
  490. #ifdef TUTTI_FRUTTI
  491.     pline("(But in fact it was biologically contaminated %s juice.)",pl_fruit);
  492. #else
  493.     pline("(But in fact it was biologically contaminated orange juice.)");
  494. #endif
  495.             if (pl_character[0] == 'H')
  496.             pline("Fortunately, you have been immunized.");
  497.             else {
  498.             int typ = rn2(A_MAX);
  499.             poisontell(typ);
  500.             (void) adjattrib(typ,
  501.                     Poison_resistance ? -1 : -rn1(4,3),
  502.                     TRUE);
  503.             if(!Poison_resistance)
  504.                 losehp(rnd(10)+5*!!(otmp->cursed),
  505.                        "contaminated potion", KILLED_BY_AN);
  506.             exercise(A_CON, FALSE);
  507.             }
  508.         }
  509.         if(Hallucination) {
  510.             You("are shocked back to your senses!");
  511.             make_hallucinated(0L,FALSE,0L);
  512.         }
  513.         break;
  514.     case POT_CONFUSION:
  515.         if(!Confusion)
  516.             if (Hallucination) {
  517.             pline("What a trippy feeling!");
  518.             unkn++;
  519.             } else
  520.             pline("Huh, What?  Where am I?");
  521.         else    nothing++;
  522.         make_confused(HConfusion + rn1(7,16-8*bcsign(otmp)),FALSE);
  523.         break;
  524.     case POT_GAIN_ABILITY:
  525.         if(otmp->cursed) {
  526.             pline("Ulch!  That potion tasted foul!");
  527.             unkn++;
  528.         } else {      /* If blessed, increase all; if not, try up to */
  529.             int itmp; /* 6 times to find one which can be increased. */
  530.             i = -1;        /* increment to 0 */
  531.             for (ii = A_MAX; ii > 0; ii--) {
  532.             i = (otmp->blessed ? i + 1 : rn2(A_MAX));
  533.             /* only give "your X is already as high as it can get"
  534.                message on last attempt (except blessed potions) */
  535.             itmp = (otmp->blessed || ii == 1) ? 0 : -1;
  536.             if (adjattrib(i, 1, itmp) && !otmp->blessed)
  537.                 break;
  538.             }
  539.         }
  540.         break;
  541.     case POT_SPEED:
  542.         if(Wounded_legs && !otmp->cursed) {
  543.             heal_legs();
  544.             unkn++;
  545.             break;
  546.         }        /* and fall through */
  547.     case SPE_HASTE_SELF:
  548.         if(!(Fast & ~INTRINSIC)) /* wwf@doe.carleton.ca */
  549.             You("are suddenly moving %sfaster.",
  550.                 Fast ? "" : "much ");
  551.         else {
  552.             Your("%s get new energy.",
  553.                 makeplural(body_part(LEG)));
  554.             unkn++;
  555.         }
  556.         exercise(A_DEX, TRUE);
  557.         Fast += rn1(10,100+60*bcsign(otmp));
  558.         break;
  559.     case POT_BLINDNESS:
  560.         if(Blind) nothing++;
  561.         make_blinded(Blinded + rn1(200, 250-125*bcsign(otmp)), TRUE);
  562.         break;
  563.     case POT_GAIN_LEVEL:
  564.         if (otmp->cursed) {
  565.             unkn++;
  566.             /* they went up a level */
  567.             if((ledger_no(&u.uz) == 1 && u.uhave.amulet) ||
  568.                               Can_rise_up(&u.uz)) {
  569.                 const char *riseup = "rise up, through the ceiling!";
  570.                 if(ledger_no(&u.uz) == 1) {
  571.                     You(riseup);
  572.                 goto_level(&earth_level, FALSE, FALSE, FALSE);
  573.                 } else {
  574.                     register int newlev = depth(&u.uz)-1;
  575.                 d_level newlevel;
  576.  
  577.                 get_level(&newlevel, newlev);
  578.                 if(on_level(&newlevel, &u.uz)) {
  579.                     pline("It tasted bad.");
  580.                     break;
  581.                 } else You(riseup);
  582.                 goto_level(&newlevel, FALSE, FALSE, FALSE);
  583.                 }
  584.             }
  585.             else You("have an uneasy feeling.");
  586.             break;
  587.         }
  588.         pluslvl();
  589.         if (otmp->blessed)
  590.             /* blessed potions place you at a random spot in the
  591.              * middle of the new level instead of the low point
  592.              */
  593.             u.uexp = rndexp();
  594.         break;
  595.     case POT_HEALING:
  596.         You("begin to feel better.");
  597.         healup(d(5,2) + 5 * bcsign(otmp),
  598.                1, !!(otmp->blessed), !(otmp->cursed));
  599.         exercise(A_STR, TRUE);
  600.         break;
  601.     case POT_EXTRA_HEALING:
  602.         You("feel much better.");
  603.         healup(d(5,4) + 5 * bcsign(otmp),
  604.                2+3*!!(otmp->blessed), !(otmp->cursed), 1);
  605.         make_hallucinated(0L,TRUE,0L);
  606.         exercise(A_STR, TRUE);
  607.         exercise(A_CON, TRUE);
  608.         break;
  609.     case POT_LEVITATION:
  610.     case SPE_LEVITATION:
  611.         if(!Levitation) {
  612.             /* kludge to ensure proper operation of float_up() */
  613.             HLevitation = 1;
  614.             float_up();
  615.             /* reverse kludge */
  616.             HLevitation = 0;
  617.             if (otmp->cursed && !Is_waterlevel(&u.uz)) {
  618.     if((u.ux != xupstair || u.uy != yupstair)
  619.        && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up)
  620.        && (!xupladder || u.ux != xupladder || u.uy != yupladder)
  621.     ) {
  622.                     You("hit your %s on the ceiling.",
  623.                         body_part(HEAD));
  624.                     losehp(uarmh ? 1 : rnd(10),
  625.                         "colliding with the ceiling",
  626.                         KILLED_BY);
  627.                 } else (void) doup();
  628.             }
  629.         } else
  630.             nothing++;
  631.         if (otmp->blessed) {
  632.             char buf[BUFSZ];
  633.             int lmoves;
  634.  
  635.             makeknown(POT_LEVITATION);
  636.             do {
  637.     getlin("How many moves do you wish to levitate for? [1-300]", buf);
  638.                 lmoves = (!*buf || *buf=='\033') ? 0 : atoi(buf);
  639.             } while (lmoves < 1 || lmoves > 300);
  640.             HLevitation += lmoves;
  641.         } else HLevitation += rnd(150);
  642.         u.uprops[LEVITATION].p_tofn = float_down;
  643.         break;
  644.     case POT_GAIN_ENERGY:            /* M. Stephenson */
  645.         {    register int     num;
  646.             if(otmp->cursed)
  647.                 You("feel lackluster.");
  648.             else
  649.                 pline("Magical energies course through your body.");
  650.             num = rnd(5) + 5 * otmp->blessed + 1;
  651.             u.uenmax += (otmp->cursed) ? -num : num;
  652.             u.uen += (otmp->cursed) ? -num : num;
  653.             if(u.uenmax <= 0) u.uenmax = 0;
  654.             if(u.uen <= 0) u.uen = 0;
  655.             flags.botl = 1;
  656.             exercise(A_WIS, TRUE);
  657.         }
  658.         break;
  659.     default:
  660.         impossible("What a funny potion! (%u)", otmp->otyp);
  661.         return(0);
  662.     }
  663.     return(-1);
  664. }
  665.  
  666. void
  667. healup(nhp, nxtra, curesick, cureblind)
  668.     int    nhp, nxtra;
  669.     register boolean curesick, cureblind;
  670. {
  671. #ifdef POLYSELF
  672.     if (u.mtimedone && nhp) {
  673.         u.mh += nhp;
  674.         if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
  675.     }
  676. #endif
  677.     if(nhp)    {
  678.         u.uhp += nhp;
  679.         if(u.uhp > u.uhpmax)    u.uhp = (u.uhpmax += nxtra);
  680.     }
  681.     if(cureblind)    make_blinded(0L,TRUE);
  682.     if(curesick)    make_sick(0L,TRUE);
  683.     flags.botl = 1;
  684.     return;
  685. }
  686.  
  687. void
  688. strange_feeling(obj,txt)
  689. register struct obj *obj;
  690. register const char *txt;
  691. {
  692.     if(flags.beginner)
  693.         You("have a %s feeling for a moment, then it passes.",
  694.         Hallucination ? "normal" : "strange");
  695.     else
  696.         pline(txt);
  697.  
  698.     if(!obj)    /* e.g., crystal ball finds no traps */
  699.         return;
  700.  
  701.     if(obj->dknown && !objects[obj->otyp].oc_name_known &&
  702.                         !objects[obj->otyp].oc_uname)
  703.         docall(obj);
  704.     useup(obj);
  705. }
  706.  
  707. const char *bottlenames[] = {
  708.     "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
  709. };
  710.  
  711. void
  712. potionhit(mon, obj)
  713. register struct monst *mon;
  714. register struct obj *obj;
  715. {
  716.     register const char *botlnam = bottlenames[rn2(SIZE(bottlenames))];
  717.     boolean distance, isyou = (mon == &youmonst);
  718.  
  719.     if(isyou) {
  720.         distance = 0;
  721.         pline("The %s crashes on your %s and breaks into shards.",
  722.             botlnam, body_part(HEAD));
  723.         losehp(rnd(2), "thrown potion", KILLED_BY_AN);
  724.     } else {
  725.         distance = distu(mon->mx,mon->my);
  726.         if (!cansee(mon->mx,mon->my)) pline("Crash!");
  727.         else {
  728.             char *mnam = mon_nam(mon);
  729.             char buf[BUFSZ];
  730.  
  731.             if(has_head(mon->data)) {
  732.             Sprintf(buf, "%s %s",
  733.                 s_suffix(mnam),
  734.                 (notonhead ? "body" : "head"));
  735.             } else {
  736.             Strcpy(buf, mnam);
  737.             }
  738.             pline("The %s crashes on %s and breaks into shards.",
  739.                botlnam, buf);
  740.         }
  741.         if(rn2(5) && mon->mhp > 1)
  742.             mon->mhp--;
  743.     }
  744.  
  745.     if (cansee(mon->mx,mon->my))
  746.         pline("%s evaporates.", The(xname(obj)));
  747.  
  748.     if (!isyou) switch (obj->otyp) {
  749.  
  750.     case POT_RESTORE_ABILITY:
  751.     case POT_GAIN_ABILITY:
  752.     case POT_HEALING:
  753.     case POT_EXTRA_HEALING:
  754.         if(mon->mhp < mon->mhpmax) {
  755.             mon->mhp = mon->mhpmax;
  756.             if (canseemon(mon))
  757.             pline("%s looks sound and hale again.", Monnam(mon));
  758.         }
  759.         break;
  760.     case POT_SICKNESS:
  761.         if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
  762.             mon->mhpmax /= 2;
  763.         if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
  764.             mon->mhp /= 2;
  765.         if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
  766.         if (canseemon(mon))
  767.             pline("%s looks rather ill.", Monnam(mon));
  768.         break;
  769.     case POT_CONFUSION:
  770.     case POT_BOOZE:
  771.         if(!resist(mon, POTION_CLASS, 0, NOTELL))  mon->mconf = TRUE;
  772.         break;
  773.     case POT_INVISIBILITY:
  774.         mon->minvis = TRUE;
  775.         newsym(mon->mx,mon->my);
  776.         break;
  777.     case POT_PARALYSIS:
  778.         if (mon->mcanmove) {
  779.             mon->mcanmove = 0;
  780.             /* really should be rnd(5) for consistency with players
  781.              * breathing potions, but...
  782.              */
  783.             mon->mfrozen = rnd(25);
  784.         }
  785.         break;
  786.     case POT_SPEED:
  787.         if (mon->mspeed == MSLOW) mon->mspeed = 0;
  788.         else mon->mspeed = MFAST;
  789.         break;
  790.     case POT_BLINDNESS:
  791.         if(haseyes(mon->data)) {
  792.             register int btmp = 64 + rn2(32) +
  793.             rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
  794.             mon->mblinded |= btmp;
  795.             mon->mcansee = 0;
  796.         }
  797.         break;
  798.     case POT_WATER:
  799.         if (is_undead(mon->data) || is_demon(mon->data)) {
  800.             if (obj->blessed) {
  801.                 pline("%s shrieks in pain!", Monnam(mon));
  802.                 mon->mhp -= d(2,6);
  803.                 if (mon->mhp <1) killed(mon);
  804.             } else if (obj->cursed) {
  805.                 if (canseemon(mon))
  806.                     pline("%s looks healthier.", Monnam(mon));
  807.                 mon->mhp += d(2,6);
  808.                 if (mon->mhp > mon->mhpmax)
  809.                     mon->mhp = mon->mhpmax;
  810.             }
  811.         } else if(mon->data == &mons[PM_GREMLIN]) {
  812.             struct monst *mtmp2 = clone_mon(mon);
  813.  
  814.             if (mtmp2) {
  815.                 mtmp2->mhpmax = (mon->mhpmax /= 2);
  816.                 if (canseemon(mon))
  817.                     pline("%s multiplies.", Monnam(mon));
  818.             }
  819.         }
  820.         break;
  821. /*
  822.     case POT_GAIN_LEVEL:
  823.     case POT_LEVITATION:
  824.     case POT_FRUIT_JUICE:
  825.     case POT_MONSTER_DETECTION:
  826.     case POT_OBJECT_DETECTION:
  827.         break;
  828. */
  829.     }
  830.     /* Note: potionbreathe() does its own docall() */
  831.     if (distance==0 || ((distance < 3) && rn2(5)))
  832.         potionbreathe(obj);
  833.     else if (obj->dknown && !objects[obj->otyp].oc_name_known &&
  834.            !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
  835.         docall(obj);
  836.     if(*u.ushops && obj->unpaid) {
  837.             register struct monst *shkp =
  838.             shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
  839.  
  840.         if(!shkp)
  841.             obj->unpaid = 0;
  842.         else {
  843.             (void)stolen_value(obj, u.ux, u.uy,
  844.                  (boolean)shkp->mpeaceful, FALSE);
  845.             subfrombill(obj, shkp);
  846.         }
  847.     }
  848.     obfree(obj, (struct obj *)0);
  849. }
  850.  
  851. void
  852. potionbreathe(obj)
  853. register struct obj *obj;
  854. {
  855.     register int i, ii, isdone;
  856.  
  857.     switch(obj->otyp) {
  858.     case POT_RESTORE_ABILITY:
  859.     case POT_GAIN_ABILITY:
  860.         if(obj->cursed) {
  861.             pline("Ulch!  That potion smells terrible!");
  862.             break;
  863.         } else {
  864.             i = rn2(A_MAX);        /* start at a random point */
  865.             for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
  866.             if(ABASE(i) < AMAX(i)) {
  867.                 ABASE(i)++;
  868.                 /* only first found if not blessed */
  869.                 isdone = !(obj->blessed);
  870.                 flags.botl = 1;
  871.             }
  872.             if(++i >= A_MAX) i = 0;
  873.             }
  874.         }
  875.         break;
  876.     case POT_HEALING:
  877.     case POT_EXTRA_HEALING:
  878.         if(u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
  879.         exercise(A_STR, TRUE);
  880.         break;
  881.     case POT_SICKNESS:
  882.         if (pl_character[0] != 'H') {
  883.             if(u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
  884.             flags.botl = 1;
  885.             exercise(A_CON, FALSE);
  886.         }
  887.         break;
  888.     case POT_HALLUCINATION:
  889.         You("have a vision for a moment.");
  890.         break;
  891.     case POT_CONFUSION:
  892.     case POT_BOOZE:
  893.         if(!Confusion)
  894.             You("feel somewhat dizzy.");
  895.         make_confused(HConfusion + rnd(5),FALSE);
  896.         break;
  897.     case POT_INVISIBILITY:
  898.         if (!See_invisible && !Invis)
  899.             pline("For an instant you could see through yourself!");
  900.         break;
  901.     case POT_PARALYSIS:
  902.         pline("Something seems to be holding you.");
  903.         nomul(-rnd(5));
  904.         exercise(A_DEX, FALSE);
  905.         break;
  906.     case POT_SPEED:
  907.         Fast += rnd(5);
  908.         Your("knees seem more flexible now.");
  909.         exercise(A_DEX, TRUE);
  910.         break;
  911.     case POT_BLINDNESS:
  912.         if (!Blind && !u.usleep) pline("It suddenly gets dark.");
  913.         make_blinded(Blinded + rnd(5),FALSE);
  914.         break;
  915.     case POT_WATER:
  916. #ifdef POLYSELF
  917.         if(u.umonnum == PM_GREMLIN) {
  918.             struct monst *mtmp;
  919.             if(mtmp = cloneu()) {
  920.             mtmp->mhpmax = (u.mhmax /= 2);
  921.             You("multiply.");
  922.             }
  923.         }
  924. #endif
  925. /*
  926.     case POT_GAIN_LEVEL:
  927.     case POT_LEVITATION:
  928.     case POT_FRUIT_JUICE:
  929.     case POT_MONSTER_DETECTION:
  930.     case POT_OBJECT_DETECTION:
  931. */
  932.         break;
  933.     }
  934.     /* note: no obfree() */
  935.     if (obj->dknown && !objects[obj->otyp].oc_name_known &&
  936.                         !objects[obj->otyp].oc_uname)
  937.         docall(obj);
  938. }
  939.  
  940. static boolean
  941. neutralizes(o1, o2)
  942. register struct obj *o1, *o2;
  943. {
  944.     switch (o1->otyp) {
  945.         case POT_SICKNESS:
  946.         case POT_HALLUCINATION:
  947.         case POT_BLINDNESS:
  948.         case POT_CONFUSION:
  949.             if (o2->otyp == POT_HEALING ||
  950.                 o2->otyp == POT_EXTRA_HEALING)
  951.                 return TRUE;
  952.         case POT_HEALING:
  953.         case POT_EXTRA_HEALING:
  954.         case UNICORN_HORN:
  955.             if (o2->otyp == POT_SICKNESS ||
  956.                 o2->otyp == POT_HALLUCINATION ||
  957.                 o2->otyp == POT_BLINDNESS ||
  958.                 o2->otyp == POT_CONFUSION)
  959.                 return TRUE;
  960.     }
  961.  
  962.     return FALSE;
  963. }
  964.  
  965. boolean
  966. get_wet(obj)
  967. register struct obj *obj;
  968. /* returns TRUE if something happened (potion should be used up) */
  969. {
  970.         if(snuff_lit(obj)) return(TRUE);
  971.  
  972.     if (obj->greased) {
  973.         grease_protect(obj,NULL,FALSE);
  974.         return(FALSE);
  975.     }
  976.     switch (obj->oclass) {
  977.         case WEAPON_CLASS:
  978.         if (!obj->oerodeproof && is_rustprone(obj) &&
  979.             (obj->oeroded < MAX_ERODE) && !rn2(10)) {
  980.             Your("%s some%s.", aobjnam(obj, "rust"),
  981.                  obj->oeroded ? " more" : "what");
  982.             obj->oeroded++;
  983.             return TRUE;
  984.         } else break;
  985.         case POTION_CLASS:
  986.         if (obj->otyp == POT_WATER) return FALSE;
  987.         Your("%s.", aobjnam(obj,"dilute"));
  988.         if (obj->spe == -1) {
  989.             obj->spe = 0;
  990.             obj->blessed = obj->cursed = FALSE;
  991.             obj->otyp = POT_WATER;
  992.         } else obj->spe--;
  993.         return TRUE;
  994.         case SCROLL_CLASS:
  995.         if (obj->otyp != SCR_BLANK_PAPER
  996. #ifdef MAIL
  997.             && obj->otyp != SCR_MAIL
  998. #endif
  999.             ) {
  1000.             if (!Blind) {
  1001.                 boolean oq1 = obj->quan == 1L;
  1002.                 pline("The scroll%s fade%s.",
  1003.                     oq1 ? "" : "s",
  1004.                     oq1 ? "s" : "");
  1005.             }
  1006.             if(obj->unpaid) {
  1007.                 subfrombill(obj, shop_keeper(*u.ushops));
  1008.                 You("erase it, you pay for it.");
  1009.                 bill_dummy_object(obj);
  1010.             }
  1011.             obj->otyp = SCR_BLANK_PAPER;
  1012.             return TRUE;
  1013.         } else break;
  1014.         case SPBOOK_CLASS:
  1015.         if (obj->otyp != SPE_BLANK_PAPER) {
  1016.  
  1017.             if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  1018.     pline("%s suddenly heats up; steam rises and it remains dry.",
  1019.                 The(xname(obj)));
  1020.             } else {
  1021.                 if (!Blind) {
  1022.                     boolean oq1 = obj->quan == 1L;
  1023.                     pline("The spellbook%s fade%s.",
  1024.                     oq1 ? "" : "s", oq1 ? "s" : "");
  1025.                 }
  1026.                 if(obj->unpaid) {
  1027.                     subfrombill(obj, shop_keeper(*u.ushops));
  1028.                     You("erase it, you pay for it.");
  1029.                     bill_dummy_object(obj);
  1030.                 }
  1031.                 obj->otyp = SPE_BLANK_PAPER;
  1032.             }
  1033.             return TRUE;
  1034.         }
  1035.     }
  1036.     Your("%s wet.", aobjnam(obj,"get"));
  1037.     return FALSE;
  1038. }
  1039.  
  1040. int
  1041. dodip()
  1042. {
  1043.     register struct obj *potion, *obj;
  1044.     const char *tmp;
  1045.     uchar here;
  1046.     char allow_all[2];
  1047.     char c;
  1048.  
  1049.     allow_all[0] = ALL_CLASSES; allow_all[1] = '\0';
  1050.     if(!(obj = getobj(allow_all, "dip")))
  1051.         return(0);
  1052.  
  1053.     here = levl[u.ux][u.uy].typ;
  1054.     /* Is there a fountain to dip into here? */
  1055.     if (IS_FOUNTAIN(here)) {
  1056.         if(yn("Dip it into the fountain?") == 'y') {
  1057.             dipfountain(obj);
  1058.             return(1);
  1059.         }
  1060.     }
  1061.         if (is_pool(u.ux,u.uy)) {
  1062.         c = (here == POOL) ? yn("Dip it into the pool?")
  1063.                    : yn("Dip it into the moat?");
  1064.         if(c == 'y') {
  1065.             (void) get_wet(obj);
  1066.             return(1);
  1067.         }
  1068.     }
  1069.  
  1070.     if(!(potion = getobj(beverages, "dip into")))
  1071.         return(0);
  1072.     if (potion == obj && potion->quan == 1L) {
  1073.         pline("That is a potion bottle, not a Klein bottle!");
  1074.         return 0;
  1075.     }
  1076.     if(potion->otyp == POT_WATER) {
  1077.         if (potion->blessed) {
  1078.             if (obj->cursed) {
  1079.                 if (!Blind)
  1080.                     Your("%s %s.",
  1081.                       aobjnam(obj, "softly glow"),
  1082.                       Hallucination ? hcolor() : amber);
  1083.                 uncurse(obj);
  1084.                 obj->bknown=1;
  1085.     poof:
  1086.                 if(!(objects[potion->otyp].oc_name_known) &&
  1087.                    !(objects[potion->otyp].oc_uname))
  1088.                     docall(potion);
  1089.                 useup(potion);
  1090.                 return(1);
  1091.             } else if(!obj->blessed) {
  1092.                 if (!Blind) {
  1093.                     tmp = Hallucination ? hcolor() : light_blue;
  1094.                     Your("%s with a%s %s aura.",
  1095.                       aobjnam(obj, "softly glow"),
  1096.                       index(vowels, *tmp) ? "n" : "", tmp);
  1097.                 }
  1098.                 bless(obj);
  1099.                 obj->bknown=1;
  1100.                 goto poof;
  1101.             }
  1102.         } else if (potion->cursed) {
  1103.             if (obj->blessed) {
  1104.                 if (!Blind)
  1105.                     Your("%s %s.", aobjnam(obj, "glow"),
  1106.                      Hallucination ? hcolor() : (const char *)"brown");
  1107.                 unbless(obj);
  1108.                 obj->bknown=1;
  1109.                 goto poof;
  1110.             } else if(!obj->cursed) {
  1111.                 if (!Blind) {
  1112.                     tmp = Hallucination ? hcolor() : Black;
  1113.                     Your("%s with a%s %s aura.",
  1114.                       aobjnam(obj, "glow"),
  1115.                       index(vowels, *tmp) ? "n" : "", tmp);
  1116.                 }
  1117.                 curse(obj);
  1118.                 obj->bknown=1;
  1119.                 goto poof;
  1120.             }
  1121.         } else
  1122.             if (get_wet(obj))
  1123.                 goto poof;
  1124.     }
  1125.     else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
  1126.         /* Mixing potions is dangerous... */
  1127.         pline("The potions mix...");
  1128.         if (obj->cursed || !rn2(10)) {
  1129.             pline("BOOM!  They explode!");
  1130.             exercise(A_STR, FALSE);
  1131.             potionbreathe(obj);
  1132.             useup(obj);
  1133.             useup(potion);
  1134.             losehp(rnd(10), "alchemic blast", KILLED_BY_AN);
  1135.             return(1);
  1136.         }
  1137.  
  1138.         obj->blessed = obj->cursed = obj->bknown = 0;
  1139.         if (Blind) obj->dknown = 0;
  1140.  
  1141.         switch (neutralizes(obj, potion) ||
  1142.             obj->spe == -1 /* diluted */ ? 1 : rnd(8)) {
  1143.             case 1:
  1144.                 obj->otyp = POT_WATER;
  1145.                 obj->blessed = obj->cursed = 0;
  1146.                 break;
  1147.             case 2:
  1148.             case 3:
  1149.                 obj->otyp = POT_SICKNESS;
  1150.                 break;
  1151.             case 4:
  1152.                 {
  1153.                   struct obj *otmp;
  1154.                   otmp = mkobj(POTION_CLASS,FALSE);
  1155.                   obj->otyp = otmp->otyp;
  1156.                   obfree(otmp, (struct obj *)0);
  1157.                 }
  1158.                 break;
  1159.             default:
  1160.                 if (!Blind)
  1161.                 pline("The mixture glows brightly and evaporates.");
  1162.                 useup(obj);
  1163.                 useup(potion);
  1164.                 return(1);
  1165.         }
  1166.  
  1167.         if (obj->otyp == POT_WATER) {
  1168.             obj->spe = 0; /* in case it was diluted before */
  1169.             pline("The mixture bubbles violently%s.",
  1170.                 Blind ? "" : ", then clears");
  1171.         } else {
  1172.             obj->spe--; /* diluted */
  1173.             if (!Blind) {
  1174.                 pline("The mixture looks %s.",
  1175.                     OBJ_DESCR(objects[obj->otyp]));
  1176.                 obj->dknown = TRUE;
  1177.             }
  1178.         }
  1179.  
  1180.         useup(potion);
  1181.         return(1);
  1182.     }
  1183.  
  1184.     if(obj->oclass == WEAPON_CLASS && obj->otyp <= SHURIKEN) {
  1185.         if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
  1186.         char buf[BUFSZ];
  1187.         Strcpy(buf, The(xname(potion)));
  1188.         pline("%s form%s a coating on %s.",
  1189.             buf, potion->quan == 1L ? "s" : "", the(xname(obj)));
  1190.         obj->opoisoned = TRUE;
  1191.         goto poof;
  1192.         } else if(obj->opoisoned &&
  1193.               (potion->otyp == POT_HEALING ||
  1194.                potion->otyp == POT_EXTRA_HEALING)) {
  1195.         pline("A coating wears off %s.", the(xname(obj)));
  1196.         obj->opoisoned = 0;
  1197.         goto poof;
  1198.         }
  1199.     }
  1200.  
  1201.     if(obj->otyp == UNICORN_HORN && neutralizes(obj, potion)) {
  1202.         /* with multiple merged potions, we should split off one and
  1203.            just clear it, but clearing them all together is easier */
  1204.         boolean more_than_one = potion->quan > 1L;
  1205.         pline("The potion%s clear%s.",
  1206.             more_than_one ? "s" : "",
  1207.             more_than_one ? "" : "s");
  1208.         potion->otyp = POT_WATER;
  1209.         potion->blessed = 0;
  1210.         potion->cursed = 0;
  1211.         potion->spe = 0;
  1212.         return(1);
  1213.     }
  1214.  
  1215.     pline("Interesting...");
  1216.     return(1);
  1217. }
  1218.  
  1219.  
  1220. void
  1221. djinni_from_bottle(obj)
  1222. register struct obj *obj;
  1223. {
  1224.     register struct monst *mtmp;
  1225.  
  1226.     if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy))){
  1227.         pline("It turns out to be empty.");
  1228.         return;
  1229.     }
  1230.  
  1231.     if (!Blind) {
  1232.         pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
  1233.         pline("%s speaks.", Monnam(mtmp));
  1234.     } else {
  1235.         You("smell acrid fumes.");
  1236.         pline("Something speaks.");
  1237.     }
  1238.  
  1239.     switch (obj->blessed ? 0 : obj->cursed ? 4 : rn2(5)) {
  1240.     case 0 : verbalize("I am in your debt.  I will grant one wish!");
  1241.         makewish();
  1242.         mongone(mtmp);
  1243.         break;
  1244.     case 1 : verbalize("Thank you for freeing me!");
  1245.         (void) tamedog(mtmp, (struct obj *)0);
  1246.         break;
  1247.     case 2 : verbalize("You freed me!");
  1248.         mtmp->mpeaceful = TRUE;
  1249.         set_malign(mtmp);
  1250.         break;
  1251.     case 3 : verbalize("It is about time!");
  1252.         pline("%s vanishes.", Monnam(mtmp));
  1253.         mongone(mtmp);
  1254.         break;
  1255.     default: verbalize("You disturbed me, fool!");
  1256.         break;
  1257.     }
  1258. }
  1259.  
  1260. #endif /* OVLB */
  1261.  
  1262. /*potion.c*/
  1263.